﻿using Bomber.TF.GameCenter.ToolCenter;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace Bomber.TF.GameCenter
{
    public static class GameHelper
    {
        private static Dictionary<SpeciesType, Type> _gameTypes;
        static GameHelper()
        {
            CreateType();
        }
        public static ToolBase CreateTool(this SpeciesType st, GameBase copy)
        {
            ToolBase? toolBase = st.CreateTool();
            if (toolBase == null) return toolBase;
            copy.CopyCoordinate(toolBase);
            toolBase.UpdateLocation();
            return toolBase;
        }
        public static ToolBase CreateTool(this SpeciesType st)
        {
            if (!_gameTypes.ContainsKey(st) || !st.IsTool()) return null;

            var type = _gameTypes[st];
            ToolBase? toolBase = Activator.CreateInstance(type) as ToolBase;
            return toolBase;
        }
        private static void CreateType()
        {
            Type attributeType = typeof(SpeciesAttribute);
            Type baseType = typeof(GameBase);
            _gameTypes = RegisterType(baseType, attributeType);
        }
        private static Dictionary<SpeciesType, Type> RegisterType(Type baseType, Type attributeType) => RegisterType(Assembly.GetEntryAssembly(), baseType, attributeType);
        private static Dictionary<SpeciesType, Type> RegisterType(Assembly assembly, Type baseType, Type attributeType)
        {
            return assembly.GetTypes().Where(t => t.IsSubclassOf(baseType) && t.GetCustomAttributes(attributeType, false).Any())
                .Select(t =>
                {
                    SpeciesAttribute? sa = t.GetCustomAttribute(attributeType, false) as SpeciesAttribute;

                    return (sa.SpeciesType, t);
                }).ToDictionary(t => t.Item1, t => t.Item2);
        }
        private static IEnumerable<Type> GetAllBaseTypes(Type type)
        {
            while (type != null)
            {
                yield return type;
                type = type.BaseType;
            }
        }
    }
}
